package lock;

import other.CountEntity;
import org.junit.jupiter.api.Test;

import java.util.concurrent.locks.ReadWriteLock;
import java.util.concurrent.locks.ReentrantLock;
import java.util.concurrent.locks.ReentrantReadWriteLock;

public class LockTest {
    @Test
    public void testReentrantLock() throws InterruptedException {
        ReentrantLock reentrantLock = new ReentrantLock();
        CountEntity count = new CountEntity();
        count.setCount(100);
        for (int i = 0; i < 100; i++) {
            new Thread(() -> {
                reentrantLock.lock();
                System.out.println(count.getCount());
                count.setCount(count.getCount() - 1);
                reentrantLock.unlock();
            }).start();
        }
        Thread.sleep(100);
    }

    @Test
    public void testReentrantReadWriteLock() throws InterruptedException {
        //读锁在该锁没有其他写锁占用时获取
        //写锁在该锁没有其他读、写占用时才会获取
        ReadWriteLock readWriteLock = new ReentrantReadWriteLock();
        new Thread(() -> {
            readWriteLock.writeLock().lock();
            try {
                System.out.println("Thread 0 started with write lock, 写锁未释放，其他线程无法获取");
                try {
                    Thread.sleep(2000);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                System.out.println("Thread 0 ended, 写锁释放");
            } finally {
                readWriteLock.writeLock().unlock();
            }
        }).start();
        new Thread(() -> {
            readWriteLock.readLock().lock();
            try {
                System.out.println("Thread 1 started with read lock, 没有其他写锁时，多个读锁可同时获取");
                try {
                    Thread.sleep(2000);
                } catch (Exception ex) {
                }
                System.out.println("Thread 1 ended");
            } finally {
                readWriteLock.readLock().unlock();
            }
        }).start();
        new Thread(() -> {
            readWriteLock.readLock().lock();
            try {
                System.out.println("Thread 2 started with read lock, 没有其他写锁时，多个读锁可同时获取");
                try {
                    Thread.sleep(2000);
                } catch (Exception ex) {
                }
                System.out.println("Thread 2 ended");
            } finally {
                readWriteLock.readLock().unlock();
            }
        }).start();
        new Thread(() -> {
            readWriteLock.writeLock().lock();
            try {
                System.out.println("Thread 3 started with write lock, 需等待其他写/读锁全部释放后，写锁才能获取");
                try {
                    Thread.sleep(2000);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                System.out.println("Thread 3 ended, 写锁释放");
            } finally {
                readWriteLock.writeLock().unlock();
            }
        }).start();
        new Thread(() -> {
            readWriteLock.writeLock().lock();
            try {
                System.out.println("Thread 4 started with write lock, 需等待其他写/读锁全部释放后，写锁才能获取");
                try {
                    Thread.sleep(2000);
                } catch (Exception ex) {
                    ex.printStackTrace();
                }
                System.out.println("Thread 4 ended, 写锁释放");
            } finally {
                readWriteLock.writeLock().unlock();
            }
        }).start();
        Thread.sleep(8100);
    }
}
